using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using System.Windows.Threading;
using System.Threading;
using Microsoft.Surface;
using Microsoft.Surface.Presentation;
using Microsoft.Surface.Presentation.Controls;
using Microsoft.Surface.Presentation.Input;
using SurfaceApplication2.Models;

namespace SurfaceApplication2
{
    /// <summary>
    /// Interaction logic for SurfaceWindow1.xaml
    /// </summary>
    public partial class SurfaceWindow1 : SurfaceWindow
    {
        /// <summary>
        /// Default constructor.
        /// </summary>
        /// 
        private ChessBoard _chessBoard;
        private MoveValidator _validator;
        private WindowBoard _windowBoard;
        //private colorPiece _playerColor;
        private ChessEngine _engine;
        private Thread _thread;
        private bool _isCpuGame;

        public SurfaceWindow1()
        {
            InitializeComponent();

            // Add handlers for window availability events
            AddWindowAvailabilityHandlers();
        }
        
        /// <summary>
        /// Occurs when the window is about to close. 
        /// </summary>
        /// <param name="e"></param>
        protected override void OnClosed(EventArgs e)
        {
            base.OnClosed(e);

            // Remove handlers for window availability events
            RemoveWindowAvailabilityHandlers();
        }

        /// <summary>
        /// Adds handlers for window availability events.
        /// </summary>
        private void AddWindowAvailabilityHandlers()
        {
            // Subscribe to surface window availability events
            ApplicationServices.WindowInteractive += OnWindowInteractive;
            ApplicationServices.WindowNoninteractive += OnWindowNoninteractive;
            ApplicationServices.WindowUnavailable += OnWindowUnavailable;
        }

        /// <summary>
        /// Removes handlers for window availability events.
        /// </summary>
        private void RemoveWindowAvailabilityHandlers()
        {
            // Unsubscribe from surface window availability events
            ApplicationServices.WindowInteractive -= OnWindowInteractive;
            ApplicationServices.WindowNoninteractive -= OnWindowNoninteractive;
            ApplicationServices.WindowUnavailable -= OnWindowUnavailable;
        }

        /// <summary>
        /// This is called when the user can interact with the application's window.
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void OnWindowInteractive(object sender, EventArgs e)
        {
            //TODO: enable audio, animations here
        }

        /// <summary>
        /// This is called when the user can see but not interact with the application's window.
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void OnWindowNoninteractive(object sender, EventArgs e)
        {
            //TODO: Disable audio here if it is enabled

            //TODO: optionally enable animations here
        }

        /// <summary>
        /// This is called when the application's window is not visible or interactive.
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void OnWindowUnavailable(object sender, EventArgs e)
        {
            //TODO: disable audio, animations here
        }

        bool _windowBoard_Chosen(int fromRow, int fromColumn, int toRow, int toColumn)
        {
            byte fromSquare = (byte)(fromRow * 16 + fromColumn);
            byte toSquare = (byte)(toRow * 16 + toColumn);

            if (CancelMove(fromSquare) == true)
                return false;

            if (_validator.IsMoveIn(fromSquare, toSquare) == false)
                return false;

            _chessBoard = _chessBoard.Move(fromSquare, toSquare);
            _validator = new MoveValidator(_chessBoard);
            _validator.Validate();
            if (_chessBoard.IsBoardValid() == false)
            {
                _chessBoard = _chessBoard.LastBoard;
                _validator = new MoveValidator(_chessBoard);
                _validator.Validate();
                return false;
            }
            Evaluator.Evaluate(_chessBoard, _validator);

            UpdateWindow();

            if (_chessBoard.IsDraw() == true)
            {
                MessageBox.Show("Draw");
                _windowBoard.Freeze();
            }
            else if (_chessBoard.IsBlancMated == true || _chessBoard.IsNoirMated == true)
            {
                MessageBox.Show("Checkmate");
                _windowBoard.Freeze();
            }

            return true;
        }

        private bool CancelMove(byte fromSquare)
        {
            if (_chessBoard.Pieces[fromSquare].type == typePiece.Rien
                || _chessBoard.Pieces[fromSquare].color != _chessBoard.NowPlays)
                return true;

            return false;
        }

        private void UpdateWindow()
        {
            SetChessboardGrid();
            if (_isCpuGame == false && _chessBoard.LastBoard == null)
                undoButton1.IsEnabled = false;
            else if (_isCpuGame == true && (_chessBoard.LastBoard == null ||
                _chessBoard.LastBoard.LastBoard == null))
                undoButton1.IsEnabled = false;
            else
                undoButton1.IsEnabled = true;
        }

        private void SetChessboardGrid()
        {
            int i, j;

            _windowBoard.SetBoard(_chessBoard);
            ChessBoardGrid.Children.Clear();
            for (i = 0; i < 8; i++)
            {
                for (j = 0; j < 8; j++)
                {
                    ChessBoardGrid.Children.Add(_windowBoard.Pieces[i, j].DisplayControl);
                }
            }
        }

        private void undoButton1_TouchDown(object sender, TouchEventArgs e)
        {
            if (_isCpuGame == false)
                _chessBoard = _chessBoard.LastBoard;
            else
                _chessBoard = _chessBoard.LastBoard.LastBoard;
            _validator = new MoveValidator(_chessBoard);
            _validator.Validate();
            UpdateWindow();
        }

        private void newGameButton1_TouchDown(object sender, TouchEventArgs e)
        {
            //Window w = new SurfaceWindow2();
            //w.Show();
            _chessBoard = new ChessBoard();
            _windowBoard = new WindowBoard();
            _validator = new MoveValidator(_chessBoard);
            _validator.Validate();
            _windowBoard.Chosen += new WindowBoard.ChosenHandler(_windowBoard_Chosen_Cpu);
            _isCpuGame = true;
            UpdateWindow();
            _engine = new ChessEngine(4);
        }
        

        private void CpuMove()
        {
            Action action = new Action(delegate()
            {
                bool finished = false;

                Action refreshAction = new Action(delegate()
                {
                    SearchProgressBar.Value++;
                });

                _engine.ProgressChanged += delegate()
                {
                    Dispatcher.BeginInvoke(refreshAction);
                };

                _chessBoard = _engine.CpuMove(_chessBoard, _validator);
                _validator = new MoveValidator(_chessBoard, true);
                _validator.Validate();

                if (_chessBoard.IsDraw() == true)
                {
                    MessageBox.Show("Draw");
                    finished = true;
                }
                else if (_chessBoard.IsBlancMated == true || _chessBoard.IsNoirMated == true)
                {
                    MessageBox.Show("Checkmate");
                    finished = true;
                }

                Action act = new Action(delegate()
                {
                    UpdateWindow();
                    if (finished == true)
                        _windowBoard.Freeze();
                });
                Dispatcher.BeginInvoke(act);

                _engine.RemoveHandler();
            });

            SearchProgressBar.Maximum = _validator.ValidMoves.Count;
            SearchProgressBar.Visibility = System.Windows.Visibility.Visible;
            SearchProgressBar.Value = 0;
            _windowBoard.Freeze();
            _thread = new Thread(new ThreadStart(action));
            _thread.Start();
        }

        bool _windowBoard_Chosen_Cpu(int fromRow, int fromColumn, int toRow, int toColumn)
        {
            byte fromSquare = (byte)(fromRow * 16 + fromColumn);
            byte toSquare = (byte)(toRow * 16 + toColumn);

            if (CancelMove(fromSquare) == true)
                return false;

            if (_validator.IsMoveIn(fromSquare, toSquare) == false)
                return false;

            _chessBoard = _chessBoard.Move(fromSquare, toSquare);
            _validator = new MoveValidator(_chessBoard);
            _validator.Validate();
            if (_chessBoard.IsBoardValid() == false)
            {
                _chessBoard = _chessBoard.LastBoard;
                _validator = new MoveValidator(_chessBoard);
                _validator.Validate();
                return false;
            }
            Evaluator.Evaluate(_chessBoard, _validator);

            UpdateWindow();

            if (_chessBoard.IsDraw() == true)
            {
                MessageBox.Show("Draw");
                _windowBoard.Freeze();
                return true;
            }
            else if (_chessBoard.IsBlancMated == true || _chessBoard.IsNoirMated == true)
            {
                MessageBox.Show("Checkmate");
                _windowBoard.Freeze();
                return true;
            }

            CpuMove();

            return true;
        }

        private void Window_Closing(object sender, System.ComponentModel.CancelEventArgs e)
        {
            if (_thread != null)
                _thread.Abort();
        }

        private void exitButton1_TouchDown(object sender, TouchEventArgs e)
        {
            Application.Current.Shutdown();
        }

     
    }
}